#!/usr/bin/env bash

# Copyright 2018 The Fuchsia Authors
#
# Use of this source code is governed by a MIT-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT

readonly SCRIPT_DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
readonly ZIRCON_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
readonly PREBUILTS_DIR="$(cd "${ZIRCON_ROOT}/prebuilt" && pwd)"
readonly ENSURE_FILE="${PREBUILTS_DIR}/zircon.ensure"
readonly VERSIONS_FILE="${PREBUILTS_DIR}/zircon.versions"
readonly GSUTIL="gsutil"
readonly GS_URL_PREFIX="gs://fuchsia"

case "$#:$1" in
0:|1:--update)
  mode=update
  ;;
1:--verify)
  mode=verify
  ;;
1:--upload)
  mode=upload
  ;;
*)
  echo >&2 "Usage: $0 [--update | --upload | --verify]"
  exit 1
  ;;
esac


find_cipd() {
  # If the Zircon checkout is part of a jiri checkout that includes
  # //buildtools, then find cipd there.  Otherwise, if cipd is in
  # the PATH, take it from there.
  type -p "${ZIRCON_ROOT}/../buildtools/cipd" || type -p cipd
}

readonly CIPD="$(find_cipd)" || {
  echo >&2 "$0: Need cipd in the PATH"
}

resolve_one_package() {
  local -r package="$1" version="$2"
  local result
  result="$($CIPD resolve "fuchsia/$package" -version "$version")" || {
    local rc=$?
    echo >&2 "$0: cipd cannot resolve fuchsia/$package -version $version"
    return $rc
  }
  echo "${package} ${result##*:}"
}

# TODO(crbug.com/827637): Use `cipd ensure-file-verify -resolve` when that
# gets implemented.
resolve_ensure_file() {
  echo "\
# This file is generated by scripts/update-prebuilt-versions.  DO NOT EDIT!
# Instead, edit zircon.ensure and run the script.
"

  local -a platforms matched_platforms
  local lhs rhs package platform
  while read lhs rhs; do
    case "$lhs" in
    '$VerifiedPlatform')
      platforms+=("$rhs")
      ;;
    '#MatchedPlatform')
      matched_platforms+=("$rhs")
      ;;
    fuchsia/*/\${platform})
      lhs="${lhs#fuchsia/}"
      package="${lhs%/*}"
      for platform in "${platforms[@]}"; do
        resolve_one_package "${package}/${platform}" "$rhs" || return
      done
      ;;
    fuchsia/*/\${os=*)
      lhs="${lhs#fuchsia/}"
      package="${lhs%/*}"
      lhs="${lhs#*=}"
      lhs="${lhs%%\}*}"
      for platform in "${platforms[@]}" "${matched_platforms[@]}"; do
        if [[ "$platform" == $lhs-* ]]; then
          resolve_one_package "${package}/${platform}" "$rhs" || return
        fi
      done
      ;;
    fuchsia/*)
      package="${lhs#fuchsia/}"
      resolve_one_package "$package" "$rhs" || return
      ;;
    esac
  done
}

do_staged_uploads() {
  local -r zipfile="$1"
  while read package instance; do
    if [[ -z "$package" || "$package" == \#* ]]; then
      continue
    fi
    rm -f "$zipfile"
    "$CIPD" pkg-fetch "fuchsia/$package" -version "$instance" -out "$zipfile"
    "$GSUTIL" cp -n "$zipfile" "${GS_URL_PREFIX}/${package}/${instance}"
  done
}

NEW_VERSIONS_FILE="$(mktemp "${PREBUILTS_DIR}/tmp.versions.XXXXXX")" || exit
trap 'rm -f "$NEW_VERSIONS_FILE"' EXIT ERR HUP INT TERM

set -e -o pipefail

resolve_ensure_file < "$ENSURE_FILE" > "$NEW_VERSIONS_FILE"

if [[ "$mode" = upload ]]; then
  cmp -s "$VERSIONS_FILE" "$NEW_VERSIONS_FILE" || {
    echo >&2 "Run $0 --update first."
    exit 1
  }
  rm -f "$NEW_VERSIONS_FILE"
  STAGING_ZIP="$(mktemp "${PREBUILTS_DIR}/tmp.zip.XXXXXX")"
  trap 'rm -f "$STAGING_ZIP"' EXIT ERR HUP INT TERM
  do_staged_uploads "$STAGING_ZIP" < "$VERSIONS_FILE"
  exit
fi

diff -u "$VERSIONS_FILE" "$NEW_VERSIONS_FILE" && exit 0
status=$?

if [[ "$mode" = update ]]; then
  mv -f "$NEW_VERSIONS_FILE" "$VERSIONS_FILE"
  exit 0
fi

exit $status
